#include "../Include/WizGeometryOrthonormalBasis.hpp"

namespace Wiz
{
    namespace OrthonormalBasis
    {
        template<class ElementT>
        ::Wiz::Void::Type Type<ElementT>::Build(tAxisIn XAxis, tAxisIn YAxis, tAxisIn ZAxis)
        {
            const tElement ZAxisDotSelf = tAxis::Dot(ZAxis, ZAxis);
            this->m_XAxis = XAxis - (tAxis::Dot(XAxis, ZAxis) / ZAxisDotSelf) * ZAxis;
            this->m_YAxis = YAxis - (tAxis::Dot(YAxis, ZAxis) / ZAxisDotSelf) * ZAxis;

            if (::Wiz::Absolute::Less<tElement>(this->m_XAxis.SqrLength(), ::Wiz::GetEpsilonSqr<tElement>()))
            {
                this->m_XAxis = tAxis::Cross(YAxis, ZAxis);
            }
            if (::Wiz::Absolute::Less<tElement>(this->m_YAxis.SqrLength(), ::Wiz::GetEpsilonSqr<tElement>()))
            {
                this->m_YAxis = tAxis::Cross(XAxis, ZAxis);
            }

            this->m_XAxis.Normalize();
            this->m_YAxis.Normalize();
            this->m_ZAxis.Normalize();
        }

        template struct Type<::Wiz::Real32::Type>;
        template struct Type<::Wiz::Real64::Type>;
    } /// end of namespace OrthonormalBasis
} /// end of namespace Wiz
